/**
 * @param {View} shell
 * @see http://www.aplweb.co.uk/blog/js/mac-like-icon-dock-v3/
 * @constructor
 */
function FilmStripMediator(shell)
{
	"use strict";

	/** @type {FilmStripMediator} */
	var _this = this;
	/** @type {Object.<String>|Object.<Number>} */
	var _smallCSS = { width: Enum.filmstrip.small, height: Enum.filmstrip.small };
	/**
	 * Amount that strip is larger than window height
	 * @type {Number}
	 * @private
	 */
	var _oversize = 0;
	var _scrolling = false;
	var _animating = false;
	var _redrawReady = false;
	var _scrollInterval;
	/** @type {Point} */
	var _mouse = new Point();
	/** @type {Rectangle} */
	var _topEdge = new Rectangle();
	/** @type {Rectangle} */
	var _bottomEdge = new Rectangle();
	/** @type {Number} */
	var _rate = Math.round(1000 / Enum.filmstrip.refreshRate);

	var $view = $('#strip-container');
	var $strip = $('#strip');
	/** @type {jQuery} */
	var $images = null;

	function init()
	{
		$view.hover(
			function() { $strip.fadeTo(400, 1); },
			function() { $strip.fadeTo(500, 0.7); }
		);
	}

	/**
	 * Capture mouse movement
	 */
	function watchMouse()
	{
		$(document).mousemove(function(e)
		{
			_mouse.X = e.pageX;
			_mouse.Y = e.pageY;
			_redrawReady = true;
			animate();
		});
	}

	/**
	 * Stop capturing mouse movement
	 */
	function ignoreMouse()
	{
		$(document).off('mousemove');
	}

	this.fit = function()
	{
		if ($strip.height() > window.innerHeight)
		{
			_oversize = ($strip.height() + Enum.filmstrip.large) - window.innerHeight;

			$strip
				.mousewheel(function(event, delta, deltaX, deltaY)
				{
					var change = $strip.offset().top + (delta * Enum.filmstrip.small);
					if (change > 0) { change = 0; }	else if (change < -_oversize) { change = -_oversize; }
					$strip.css({ 'top': change });
				});

			var offset = $strip.offset();
			_topEdge.topLeft.Y = offset.top;
			_topEdge.topLeft.X = offset.left;
			_topEdge.bottomRight.X = _topEdge.topLeft.X + $strip.width();
			_topEdge.bottomRight.Y = _topEdge.topLeft.Y + Enum.filmstrip.small;

			_topEdge.copyTo(_bottomEdge);

			_bottomEdge.bottomRight.Y = window.innerHeight;
			_bottomEdge.topLeft.Y = _bottomEdge.bottomRight.Y - Enum.filmstrip.small;
		}
		else
		{
			_oversize = 0;
			$strip.unmousewheel();
		}
	};

	this.show = function()
	{
		ignoreMouse();
		$strip.empty();
		for (var i = 0; i < Session.set.photos.length; i++) { addPhoto(Session.set.photos[i]); }
		_this.fit();
		$images = $strip.find('img');
		watchMouse();
	};

	/**
	 *
	 * @return {FilmStripMediator}
	 */
	this.enable = function()
	{
		if ($images != null && $images.size() > 0) { watchMouse(); }
		return _this;
	};

	/**
	 *
	 * @return {FilmStripMediator}
	 */
	this.disable = function()
	{
		ignoreMouse();
		collapse();
		return _this;
	};

	/**
	 * Reset all thumbs to small size
	 */
	function collapse()
	{
		$images.css({ width: Enum.filmstrip.small, height: Enum.filmstrip.small });
	}

	/**
	 *
	 * @param {Photo} photo
	 */
	function addPhoto(photo)
	{
		$('<img>')
			.attr('id', makeID(photo))
			.attr('src', photo.stripSize.url)
			.css(_smallCSS)
			.click(function(e) { _this.handlePhotoClick(photo); })
			.appendTo($strip);
	}

//- Thumb sizing --------------------------------------------------------------

	function animate()
	{
		if (!_animating)
		{
			_animating = true;
			window.setTimeout(updateSizes, _rate);
		}
	}

	/**
	 * @see http://www.aplweb.co.uk/blog/js/mac-like-icon-dock-v3/
	 */
	function updateSizes()
	{
		_animating = false;

		if (_oversize > 0 && _mouse.inside(_bottomEdge))
		{
			if (!_scrolling) { beginScroll(); }
		}
		else if (_oversize > 0 && _mouse.inside(_topEdge))
		{
			if (!_scrolling) { beginScroll(true); }
		}
		else
		{
			/**
			 * Cursor distance from thumbnail before it resizes
			 * @type {Number}
			 */
			var proximity = 200;
			var sizeDiff = Enum.filmstrip.large - Enum.filmstrip.small;

			endScroll();

			$images.each(function()
			{
				// find the distance from the center of each icon
				var $img = $(this);
				var center = new Point(
					$img.offset().left + ($img.outerWidth()/2.0),
					$img.offset().top + ($img.outerHeight()/2.0)
				);
				var dist = _mouse.distance(center);
				// determine the new sizes of the icons from the mouse distance from their centers
				var newSize = (1 - Math.min(1, Math.max(0, dist/proximity))) * sizeDiff + Enum.filmstrip.small;

				$(this).css({width: newSize, height: newSize});
			});
		}

		if (_redrawReady)
		{
			_redrawReady = false;
			animate();
		}
	}

//- Scrolling -----------------------------------------------------------------

	/**
	 * @param {Boolean} [up = false]
	 */
	function beginScroll(up)
	{
		var top = $strip.offset().top - _topEdge.topLeft.Y;
		var step = up ? 5 : -5;

		if ((step > 0 && top < 0) || (step < 0 && top > -_oversize))
		{
			collapse();

			_scrolling = true;

			_scrollInterval = window.setInterval(function()
			{
				top += step;

				if (top > 0)
				{
					top = 0;
					endScroll();
				}
				else if (top < -_oversize)
				{
					top = -_oversize;
					endScroll();
				}
				$strip.css({ top: top });
			},
				_rate);
		}
	}

	function endScroll()
	{
		window.clearInterval(_scrollInterval);
		_scrolling = false;
	}

	this.select = function()
	{
		if (_this.visible)
		{
			$images.removeClass('selected');
			$('#' + makeID(Session.photo)).addClass('selected');
		}
	};

	/**
	 * @param {Photo} photo
	 * @return {String}
	 */
	function makeID(photo) { return 'strip-' + photo.id; }

	/**
	 * Shadow to implement
	 * @param {Photo} photo
	 */
	this.handlePhotoClick = function(photo) { };

	init();
}